using System;

using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Updating;
using DevExpress.Xpo;
using DevExpress.Data.Filtering;
using DevExpress.Persistent.BaseImpl;
using DevExpress.ExpressApp.Security;

namespace AppSolution.Module
{
    public class Updater : ModuleUpdater
    {
        public Updater(ObjectSpace objectSpace, Version currentDBVersion) : base(objectSpace, currentDBVersion) { }
        public override void UpdateDatabaseAfterUpdateSchema()
        {
            base.UpdateDatabaseAfterUpdateSchema();

            
            if (ObjectSpace.FindObject<TestObject>(new BinaryOperator("Id", 1)) == null)
            {
                TestObject os = new TestObject(ObjectSpace.Session);
                os.Id = 1;
                //os.MyMenu = new MenuList();
                //os.MyMenu.ID = 10;
                os.Save();
                
            }
            Role admins = CreateRole("Administrator");
            admins.AddPermission(new ConditionalObjectAccessPermission(typeof(Employee), ObjectAccess.Delete, ObjectAccessModifier.Allow) { Condition = "[FullName] Like 'Felipe%'" });
            admins.AddPermission(new ConditionalObjectAccessPermission(typeof(Employee), ObjectAccess.Delete, ObjectAccessModifier.Deny) { Condition = "[FullName] Like 'Vitor%'" });
            admins.AddPermission(new ConditionalObjectAccessPermission(typeof(Employee), ObjectAccess.Delete, ObjectAccessModifier.Deny));
            admins.Save();
            AddUserToRole("Admin", "admin", "Administrator", admins);

            Role staff = CreateRole("Staff");
            staff.AddPermission(new ConditionalObjectAccessPermission(typeof(Employee), ObjectAccess.Delete, ObjectAccessModifier.Allow) { Condition = "[FullName] Like 'Felipe%'" });
            staff.AddPermission(new ConditionalObjectAccessPermission(typeof(Employee), ObjectAccess.Delete, ObjectAccessModifier.Deny) { Condition = "[FullName] Like 'Vitor%'" });
            // the following OVERRIDES all previous conditional permissions because of code inside DeleteObjectViewController that tests if the delete action should be enabled 
            // without passing the current object or testing the selected objects, effectivelly IMPOSING the more general permission over the object's specific permissions...
            // to avoid this behavior, use the ConditionalObjectAccessPermission without a permission, because it only applies to individual objects (see the Admin conditions above!)
            staff.AddPermission(new ObjectAccessPermission(typeof(Employee), ObjectAccess.Delete, ObjectAccessModifier.Deny));
            staff.Save();
            AddUserToRole("User", "user", "StaffUser", staff);

        }
        Role CreateRole(string roleName)
        {
            // if the role does not exist, create it
            Role role =
                ObjectSpace.FindObject<Role>(new BinaryOperator("Name", roleName)) ??
                ObjectSpace.CreateObject<Role>();
            role.Name = roleName;
            // remove all currently assigned permissions to the bundled roles
            while (role.PersistentPermissions.Count > 0)
                ObjectSpace.Delete(role.PersistentPermissions[0]);
            // Allow full access to all objects (this should be added to all Roles by default)
            role.AddPermission(new ObjectAccessPermission(typeof(object), ObjectAccess.AllAccess));
            return role;
        }

        User AddUserToRole(string userName, string password, string personName, Role role)
        {
            User user = ObjectSpace.FindObject<User>(new BinaryOperator("UserName", userName));
            if (user == null)
            {
                user = ObjectSpace.CreateObject<User>();
                user.UserName = userName;
                user.FirstName = personName;
                user.SetPassword(password);
            }
            user.Roles.Add(role);
            user.Save();
            return user;
        }
    }
}
